//
// Created by hamlet on 2022/1/13.
//

#ifndef SNAKE_GAME_MAINWINDOW_H
#define SNAKE_GAME_MAINWINDOW_H

#include <unordered_map>
#include <vector>
#include <QMainWindow>
#include <QSettings>
#include "room.h"

class NewFruitMessage;
class PlayerInfo;
class RoomInfo;
class WorldWidget;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
class QCheckBox;
class QListWidget;
class QListWidgetItem;
class QWebSocket;
class QWebSocketServer;
class QUdpSocket;
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
    static constexpr int SEARCH_PORT{30314};
    static constexpr int GAME_PORT{21221};

    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow() override;

protected slots:
    void timerEvent(QTimerEvent *event) override;
    void keyPressEvent(QKeyEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private slots:
    /**************************** PAGE_START *************************************/
    void slot_S_start();

    /************************** PAGE_RECEPTION ***********************************/
    void slot_R_receiveRoomList();
    void slot_R_makeRoom();

    /************************** PAGE_MAKE_ROOM ***********************************/
    void slot_MR_chooseAll(bool state);
    void slot_MR_chooseAllCheck();
    void slot_MR_NO_timeLimit(bool state);
    void slot_MR_NO_lifeLimit(bool state);
    void slot_MR_GO();
    void slot_MR_cancel();

    /************************** PAGE_WAITING_HALL ********************************/
    void slot_WH_client_tryConnect(QListWidgetItem *item);
    void slot_WH_client_onConnected();
    void slot_WH_server_startServer();
    void slot_WH_server_onNewConnection();
    void slot_WH_startGame();
    void slot_WH_cancel();
    void slot_WH_sendChatText();

    /******************************* GAMING **************************************/
    void slot_client_processTextMessage(const QString &message_data);
    void slot_client_processBinaryMessage(const QByteArray &message_data);
    void slot_client_socketDisconnected();
    void slot_server_processTextMessage(const QString &message_data);
    void slot_server_processBinaryMessage(const QByteArray &message_data);
    void slot_server_socketDisconnected();

    void slot_server_newFruit(NewFruitMessage *message);

private:
    static constexpr int SEND_INTERVAL{500};
    static constexpr int CHECK_INTERVAL{30000};

    Ui::MainWindow *ui;

    PlayerInfo *m_playerInfo = nullptr;
    RoomInfo   *m_roomInfo   = nullptr;

    void mod_searchServer_enabled(bool state);
    void mod_sendServerInfo_enabled(bool state);

    QUdpSocket *m_udpSocket = nullptr;
    int m_timerId_R  = 0;
    int m_timerId_MR = 0;

    std::unordered_map<qint64, size_t> m_roomList;
    std::vector<RoomInfo*>             m_roomList_self;
    std::vector<int>                   m_roomList_time;
    std::vector<QListWidgetItem*>      m_roomList_item;

    std::vector<QCheckBox*>                             m_MR_fruit_allCheckBox;
    std::unordered_map<QCheckBox*, RoomInfo::FruitType> m_MR_checkBox2fruitMap;
    QByteArray m_sendData;

    QWebSocket *m_client = nullptr;
    std::unordered_map<qint64, size_t> m_playerList;
    std::vector<PlayerInfo*>           m_playerList_self;
    std::vector<QListWidgetItem*>      m_playerList_item;

    QWebSocketServer *m_server = nullptr;
    std::unordered_map<QWebSocket*, size_t> m_server_playerList;
    QString                                 m_server_chatText;

    WorldWidget *m_world = nullptr;

    void server_deletePlayer(QWebSocket *sock);
    bool m_aboutToDeleteServer = false;

    template<typename T>
    inline T getValueOrDefault(const QSettings &settings, const QString &key, const T &default_value);
    static QByteArray jsonToByteArray(const QJsonObject &json);
    static QJsonObject byteArrayToJson(const QByteArray &byteArray);
    static QString timeInfoString();

    static QListWidgetItem *addItemAndSetColor(QListWidget *listWidget, const QString &text, QColor color={});
    static QListWidgetItem *deleteItemTotally(QListWidget *listWidget, QListWidgetItem *item);
};


#endif //SNAKE_GAME_MAINWINDOW_H
